package com.example.opencv_demo.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import com.example.opencv_demo.R;
import com.example.opencv_demo.adapter.TextAdapter;
import com.ohuang.crashhandler.CrashHandler;

import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class MainActivity2 extends ImageDemoActivity {


    public void btnClick2() {
        imageView.setImageBitmap(srcBitmap);
    }

    /**
     * 均值模糊
     *
     * @param
     */
    public void btn0Click2() {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();
        //均值模糊
        Imgproc.blur(srcMat, mat, new Size(15, 15), new Point(-1, -1));
        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    /**
     * 高斯模糊
     *
     * @param
     */
    public void btn1Click2() {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();
        //高斯模糊  size里面必须是奇数
        Imgproc.GaussianBlur(srcMat, mat, new Size(15, 15), 0);
        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    /**
     * 中值滤波
     */
    public void btn2Click2() {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();
        //中值滤波  size里面必须是奇数
        Imgproc.medianBlur(srcMat, mat, 15);
        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    /**
     * 最大值滤波  膨胀
     */
    public void btn3Click2() {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();
        //获取结构元素的方法
        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5));
        Imgproc.dilate(srcMat, mat, kernel);
        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    /**
     * 最小值滤波 腐蚀
     */
    public void btn4Click2() {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();
        //获取结构元素的方法
        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5));
        Imgproc.erode(srcMat, mat, kernel);
        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    /**
     * 高斯双边滤波函数
     */
    public void btn5Click2() {
        if (fileName == null) {
            Toast.makeText(this, "请重新选择图片", Toast.LENGTH_LONG).show();
            return;
        }

        Log.d("TAG", "btn5Click2: " + fileName);
        Mat src = Imgcodecs.imread(fileName);


        Mat mat = new Mat();


        Imgproc.bilateralFilter(src, mat, 0, 150, 15);//高斯双边滤波函数

        Bitmap bm = Bitmap.createBitmap(src.cols(), src.rows(), Bitmap.Config.ARGB_8888);
        Mat result = new Mat();
        Imgproc.cvtColor(mat, result, Imgproc.COLOR_BGR2RGBA);
        Utils.matToBitmap(result, bm);

        imageView.setImageBitmap(bm);
        src.release();
        mat.release();
    }

    /**
     * 均值迁移滤波
     */
    public void btn6Click2() {
        if (fileName == null) {
            Toast.makeText(this, "请重新选择图片", Toast.LENGTH_LONG).show();
            return;
        }
        Mat src = Imgcodecs.imread(fileName);

        Mat mat = new Mat();


        Imgproc.pyrMeanShiftFiltering(src, mat, 10, 50);//均值迁移滤波

        Bitmap bm = Bitmap.createBitmap(src.cols(), src.rows(), Bitmap.Config.ARGB_8888);
        Mat result = new Mat();
        Imgproc.cvtColor(mat, result, Imgproc.COLOR_BGR2RGBA);
        Utils.matToBitmap(result, bm);

        imageView.setImageBitmap(bm);
        src.release();
        mat.release();
    }

    @Override
    public void initData() {
        mData.add(new TextAdapter.RunnableBean("显示原图", new Runnable() {
            @Override
            public void run() {
                btnClick2();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("均值模糊", new Runnable() {
            @Override
            public void run() {
                btn0Click2();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("高斯模糊", new Runnable() {
            @Override
            public void run() {
                btn1Click2();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("中值滤波", new Runnable() {
            @Override
            public void run() {
                btn2Click2();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("最大值滤波(膨胀)", new Runnable() {
            @Override
            public void run() {
                btn3Click2();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("最小值滤波（腐蚀）", new Runnable() {
            @Override
            public void run() {
                btn4Click2();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("高斯双边滤波函数", new Runnable() {
            @Override
            public void run() {
                btn5Click2();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("均值迁移滤波", new Runnable() {
            @Override
            public void run() {
                btn6Click2();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("自定义滤波", new Runnable() {
            @Override
            public void run() {
                btn7Click2();
            }
        }));

        mData.add(new TextAdapter.RunnableBean("膨胀", new Runnable() {
            @Override
            public void run() {
                morphologyShow(0);
            }
        }));
        mData.add(new TextAdapter.RunnableBean("腐蚀", new Runnable() {
            @Override
            public void run() {
                morphologyShow(1);
            }
        }));
        mData.add(new TextAdapter.RunnableBean("开操作", new Runnable() {
            @Override
            public void run() {
                morphologyShow(2);
            }
        }));
        mData.add(new TextAdapter.RunnableBean("闭操作", new Runnable() {
            @Override
            public void run() {
                morphologyShow(3);
            }
        }));
        mData.add(new TextAdapter.RunnableBean("黑帽", new Runnable() {
            @Override
            public void run() {
                morphologyShow(4);
            }
        }));
        mData.add(new TextAdapter.RunnableBean("顶帽", new Runnable() {
            @Override
            public void run() {
                morphologyShow(5);
            }
        }));
        mData.add(new TextAdapter.RunnableBean("基本梯度", new Runnable() {
            @Override
            public void run() {
                morphologyShow(6);
            }
        }));
        mData.add(new TextAdapter.RunnableBean("阈值", new Runnable() {
            @Override
            public void run() {
                thresholdShow();
            }
        }));
        mData.add(new TextAdapter.RunnableBean("adp阈值", new Runnable() {
            @Override
            public void run() {
                adpThresholdShow();
            }
        }));

    }

    /**
     * 自定义滤波
     */
    public void btn7Click2() {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();


        customFilter(srcMat, mat, 3);


        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    /**
     * 自定义滤波
     *
     * @param src
     * @param dst
     * @param type
     */
    private void customFilter(Mat src, Mat dst, int type) {
        if (type == 1) {
            Mat k = new Mat(3, 3, CvType.CV_32FC1);
            float[] data = new float[]{1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f,
                    1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f,
                    1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f};
            k.put(0, 0, data);
            Imgproc.filter2D(src, dst, -1, k);
        } else if (type == 2) {
            Mat k = new Mat(3, 3, CvType.CV_32FC1);
            float[] data = new float[]{0, 1.0f / 8.0f, 0,
                    1.0f / 8.0f, 0.5f, 1.0f / 8.0f,
                    0, 1.0f / 8.0f, 0};
            k.put(0, 0, data);
            Imgproc.filter2D(src, dst, -1, k);
        } else if (type == 3) {
            Mat kx = new Mat(3, 3, CvType.CV_32FC1);
            Mat ky = new Mat(3, 3, CvType.CV_32FC1);

            float[] robert_x = new float[]{-1, 0, 0, 1};
            kx.put(0, 0, robert_x);

            float[] robert_y = new float[]{0, 1, -1, 0};
            ky.put(0, 0, robert_y);

            Imgproc.filter2D(src, dst, -1, kx);
            Imgproc.filter2D(src, dst, -1, ky);
        }
    }


    public void morphologyShow(int op) {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();


        morphologyDemo(srcMat, mat, op);


        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    /**
     * 形态学演示
     *
     * @param src
     * @param dst
     * @param option
     */
    private void morphologyDemo(Mat src, Mat dst, int option) {

        // 创建结构元素
        Mat k = Imgproc.getStructuringElement(
                Imgproc.MORPH_RECT, new Size(15, 15), new Point(-1, -1));

        // 形态学操作
        switch (option) {
            case 0: // 膨胀
                Imgproc.morphologyEx(src, dst, Imgproc.MORPH_DILATE, k);
                break;
            case 1: // 腐蚀
                Imgproc.morphologyEx(src, dst, Imgproc.MORPH_ERODE, k);
                break;
            case 2: // 开操作
                Imgproc.morphologyEx(src, dst, Imgproc.MORPH_OPEN, k);
                break;
            case 3: // 闭操作
                Imgproc.morphologyEx(src, dst, Imgproc.MORPH_CLOSE, k);
                break;
            case 4: // 黑帽
                Imgproc.morphologyEx(src, dst, Imgproc.MORPH_BLACKHAT, k);
                break;
            case 5: // 顶帽
                Imgproc.morphologyEx(src, dst, Imgproc.MORPH_TOPHAT, k);
                break;
            case 6: // 基本梯度
                Imgproc.morphologyEx(src, dst, Imgproc.MORPH_GRADIENT, k);
                break;
            default:
                break;
        }
    }

    public void thresholdShow() {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();


        thresholdDemo(srcMat, mat);


        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    /**
     * 阈值
     *
     * @param src
     * @param dst
     */
    private void thresholdDemo(Mat src, Mat dst) {
        int t = 127;
        int maxValue = 255;
        Mat gray = new Mat();
        Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
        //Imgproc.threshold(gray, dst, t, maxValue, Imgproc.THRESH_BINARY | Imgproc.THRESH_TRIANGLE);
        Imgproc.threshold(gray, dst, t, maxValue, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
        gray.release();
    }

    public void adpThresholdShow() {
        grayBitmap = srcBitmap.copy(Bitmap.Config.RGB_565, true);
        Mat srcMat = new Mat();
        Utils.bitmapToMat(grayBitmap, srcMat, true);
        Mat mat = new Mat();


        adpThresholdDemo(srcMat, mat);


        Utils.matToBitmap(mat, grayBitmap, true);
        imageView.setImageBitmap(grayBitmap);
        srcMat.release();
        mat.release();
    }

    private void adpThresholdDemo(Mat src, Mat dst) {

        int maxValue = 255;
        Mat gray = new Mat();
        Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
        Imgproc.adaptiveThreshold(gray, dst, maxValue,
                Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 15, 10);
        gray.release();
    }
}